package grape.base.rest.user.mvc;

import com.baomidou.mybatisplus.core.metadata.IPage;
import grape.base.rest.dataconstraint.mapper.DataScopeWebMapper;
import grape.base.rest.dataconstraint.vo.DataScopeVo;
import grape.base.rest.func.mapper.FuncWebMapper;
import grape.base.rest.func.vo.FuncVo;
import grape.base.rest.role.mapper.RoleWebMapper;
import grape.base.rest.role.vo.RoleVo;
import grape.base.rest.user.UserLoginHelperDto;
import grape.base.rest.user.UserLoginHelperService;
import grape.base.rest.user.form.*;
import grape.base.rest.user.mapper.UserWebMapper;
import grape.base.rest.user.vo.UserinfoAdditionalVo;
import grape.base.rest.user.vo.UserinfoVo;
import grape.base.rest.user.vo.UserVo;
import grape.base.rest.userpost.mapper.UserPostWebMapper;
import grape.base.rest.userpost.vo.UserPostVo;
import grape.base.service.dataconstraint.po.DataScope;
import grape.base.service.func.po.Func;
import grape.base.service.role.po.Role;
import grape.base.service.user.api.IUserService;
import grape.base.service.user.dto.UserCreateParam;
import grape.base.service.user.po.User;
import grape.base.service.user.query.UserListQuery;
import grape.base.service.userpost.api.IUserPostService;
import grape.base.service.userpost.po.UserPost;
import grape.common.exception.ExceptionTools;
import grape.common.rest.mvc.BaseController;
import grape.common.service.common.dataconstraint.DefaultDataObject;
import grape.common.service.common.dataconstraint.IDataObject;
import grape.common.service.loginuser.LoginUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


/**
 * <p>
 * 后台管理用户表 前端控制器
 * </p>
 *
 * @author yangwei
 * @since 2019-09-23
 */
@RestController
@RequestMapping("/base/user")
@Api(tags = "用户相关接口")
public class UserController extends BaseController<UserVo, User> {

    // 默认的数据对象编码
    public static final IDataObject<?> defaultDataObjectCode = new DefaultDataObject("dataObjectCodeUser");
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private IUserService iUserService;

    @Autowired
    private UserWebMapper userWebMapper;

    @Autowired
    private UserPostWebMapper userPostWebMapper;

    @Autowired
    private IUserPostService iUserPostService;

    @Autowired
    private UserLoginHelperService userLoginHelperService;

    @Autowired
    private RoleWebMapper roleWebMapper;
    @Autowired
    private DataScopeWebMapper dataScopeWebMapper;
    @Autowired
    private FuncWebMapper funcWebMapper;

    /**
     * 开启全局
     * @return
     */
    @Override
    public boolean isEnableDefaultDataObject() {
        // 判断是否存在关闭的情况
        if (getEnableDefaultDataObjectKeyValue() != null) {
            return (boolean) getEnableDefaultDataObjectKeyValue();
        }
        enableDefaultDataObject();
        return super.isEnableDefaultDataObject();
    }

    @Override
    protected String defaultDataObjectCode() {
        return defaultDataObjectCode.dataObjectCode();
    }

     @ApiOperation(value = "添加用户",notes = "添加用户的基本信息")
     @PreAuthorize("hasAuthority('user:single:create')")
     @PostMapping
     @ResponseStatus(HttpStatus.CREATED)
     public UserVo create(@RequestBody @Valid UserCreateForm cf) {
         UserCreateParam param =  userWebMapper.formToParam(cf);
         param.setPassword(passwordEncoder.encode(cf.getPwd()));
         UserVo vo = userWebMapper.poToVo(iUserService.createUser(param));
         return transVo(vo);
     }

     @ApiOperation(value = "查询用户",notes = "根据id查询用户")
     @PreAuthorize("hasAuthority('user:single:queryById')")
     @GetMapping("/{id}")
     @ResponseStatus(HttpStatus.OK)
     public UserVo queryById(@PathVariable String id) {
         return super.queryById(id);
     }

     @ApiOperation(value = "更新用户",notes = "更新用户基本信息")
     @PreAuthorize("hasAuthority('user:single:updateById')")
     @PutMapping("/{id}")
     @ResponseStatus(HttpStatus.CREATED)
     public UserVo update(@PathVariable String id,@RequestBody @Valid UserUpdateForm uf) {
         User user = userWebMapper.formToPo(uf);
         user.setId(id);
         return super.update(user);
     }

    @ApiOperation("分页查询用户")
    @PreAuthorize("hasAuthority('user:single:listPage')")
    @GetMapping("/listPage")
    @ResponseStatus(HttpStatus.OK)
    public IPage<UserVo> listPage(UserListPageForm listPageForm) {
        User user = userWebMapper.formToPo(listPageForm);
        UserListQuery userListPageQuery = new UserListQuery();
        userListPageQuery.setPoQuery(user);
        userListPageQuery.setNickname(user.getNickname());
        return super.listPage(userListPageQuery,listPageForm);
     }

    /**
     * 主要用于下拉搜索
     * @param listForm
     * @return
     */
    @ApiOperation(value = "不分页查询用户")
    @PreAuthorize("hasAuthority('user:single:list')")
    @GetMapping("/list")
    @ResponseStatus(HttpStatus.OK)
    public List<UserVo> list(UserListForm listForm) {
        User user = userWebMapper.formToPo(listForm);
        UserListQuery userListQuery = new UserListQuery();
        userListQuery.setPoQuery(user);
        userListQuery.setNickname(user.getNickname());
        return super.list(userListQuery);
    }
    /**
     * 启用或锁定
     * @param id
     * @param form
     * @return
     */
    @ApiOperation("启用或锁定")
    @PreAuthorize("hasAuthority('user:single:enable')")
    @PatchMapping("/{id}")
    @ResponseStatus(HttpStatus.CREATED)
    public UserVo enable(@PathVariable String id, @RequestBody @Valid UserEnableForm form) {
        User user = new User();
        user.setId(id);
        user.setIsLock(form.getIsLock());
        user.setVersion(form.getVersion());
        user.setLockReason(form.getLockReason());
        return super.update(user);
    }
    /**
     * 查看用户详情信息
     * @return
     */
    @ApiOperation("查看用户详情信息")
    @PreAuthorize("hasAuthority('user:userinfo')")
    @GetMapping("/{userId}/userinfo")
    @ResponseStatus(HttpStatus.OK)
    public UserinfoVo userinfo(@PathVariable String userId) {

        UserinfoVo currentUserinfoVo = doUserinfo(userId);
        Boolean isSuperAdmin = false;
        if (!isEmpty(currentUserinfoVo.getRoleVos())) {
            List<String> roleCodes = currentUserinfoVo.getRoleVos().stream().map(item->item.getCode()).collect(Collectors.toList());
            isSuperAdmin = userLoginHelperService.superAdminByCode(roleCodes);

        }
        currentUserinfoVo.setIsSuperAdmin(isSuperAdmin);
        return currentUserinfoVo;
    }

    /**
     * 用户信息内部方法
     * @param userId
     * @return
     */
    private UserinfoVo doUserinfo(String userId) {
        UserinfoVo userinfoVo = new UserinfoVo();
        userinfoVo.setId(userId);
        User user = iUserService.getById(userId);
        userinfoVo.setUser(transVo(userWebMapper.poToVo(user)));
        // 岗位信息
        List<UserPost> userPosts = iUserPostService.getByUserId(userId, null, null);
        if (!isEmpty(userPosts)) {
            List<UserPostVo> userPostVos = userPosts.stream().map(userPost -> userPostWebMapper.poToVo(userPost)).collect(Collectors.toList());
            userinfoVo.setUserPosts(userPostVos);
        }
        additionalUserinfo(userinfoVo,userId);
        return userinfoVo;
    }
    /**
     * 后台管理用户登录成功后获取当前登录用户信息
     * @return
     */
    @ApiOperation("当前登录用户信息")
    @PreAuthorize("hasAuthority('user')")
    @GetMapping("/userinfo/current")
    @ResponseStatus(HttpStatus.OK)
    public UserinfoVo currentUserinfo(@ApiIgnore LoginUser loginUser) {

        UserinfoVo currentUserinfoVo = doUserinfo(loginUser.getId());
        // 基本信息
        currentUserinfoVo.setId(loginUser.getId());
        currentUserinfoVo.setIsSuperAdmin(loginUser.isSuperAdmin());
        currentUserinfoVo.setIdentifierTypeLoginDictId(loginUser.getIdentifierTypeDictId());
        return currentUserinfoVo;
    }

    /**
     * 额外信息补充，包括角色，功能，数据范围约束信息
     * @param currentUserinfoVo
     * @param userId
     */
    private void additionalUserinfo(UserinfoVo currentUserinfoVo,String userId){
        // 角色信息
        UserLoginHelperDto<UserLoginHelperService.RoleFrom, Role> rolesByUserId = userLoginHelperService.getRolesByUserId(userId);
        List<Role> rolesByUserIdAll = rolesByUserId.getAll();
        if (!isEmpty(rolesByUserIdAll)) {
            List<RoleVo> roleVos = rolesByUserIdAll.stream().map(role -> roleWebMapper.poToVo(role)).collect(Collectors.toList());
            currentUserinfoVo.setRoleVos(roleVos);
        }
        UserinfoAdditionalVo<RoleVo> roleAdditionalVo = null;
        List<UserinfoAdditionalVo<RoleVo>> roleAdditionalVos = new ArrayList<>();
        List<Role> roles = null;
        for (UserLoginHelperService.RoleFrom roleFrom : rolesByUserId.getDataMap().keySet()) {
            roles = rolesByUserId.getDataMap().get(roleFrom);
            if (!isEmpty(roles)) {
                roleAdditionalVo = new UserinfoAdditionalVo();
                roleAdditionalVo.setCode(roleFrom.name());
                roleAdditionalVo.setDesc(roleFrom.getDesc());
                roleAdditionalVo.setData(roles.stream().map(role -> roleWebMapper.poToVo(role)).collect(Collectors.toList()));
                roleAdditionalVos.add(roleAdditionalVo);
            }
        }
        currentUserinfoVo.setRoleAddtionalVos(roleAdditionalVos);

        // 功能信息
        UserLoginHelperDto<UserLoginHelperService.FuncFrom, Func> funcsByUserId = userLoginHelperService.getFuncsByUserId(userId);
        List<Func> funcsByUserIdAll = funcsByUserId.getAll();
        if (!isEmpty(funcsByUserIdAll)) {
            List<FuncVo> funcVos = funcsByUserIdAll.stream().map(func -> funcWebMapper.poToVo(func)).collect(Collectors.toList());
            currentUserinfoVo.setFuncVos(funcVos);
        }
        UserinfoAdditionalVo<FuncVo> funcAdditionalVo = null;
        List<UserinfoAdditionalVo<FuncVo>> funcAdditionalVos = new ArrayList<>();
        List<Func> funcs = null;
        for (UserLoginHelperService.FuncFrom funcFrom : funcsByUserId.getDataMap().keySet()) {
            funcs = funcsByUserId.getDataMap().get(funcFrom);
            if (!isEmpty(funcs)) {
                funcAdditionalVo = new UserinfoAdditionalVo();
                funcAdditionalVo.setData(funcs.stream().map(func -> funcWebMapper.poToVo(func)).collect(Collectors.toList()));
                funcAdditionalVos.add(funcAdditionalVo);
            }
        }
        currentUserinfoVo.setFuncAddtionalVos(funcAdditionalVos);

        // 数据范围信息
        UserLoginHelperDto<UserLoginHelperService.DataScopeFrom, DataScope> dataScopesByUserId = userLoginHelperService.getDataScopesByUserId(userId);
        List<DataScope> dataScopesByUserIdAll = dataScopesByUserId.getAll();
        if (!isEmpty(dataScopesByUserIdAll)) {
            List<DataScopeVo> dataScopeVos = dataScopesByUserIdAll.stream().map(dataScope -> dataScopeWebMapper.poToVo(dataScope)).collect(Collectors.toList());
            currentUserinfoVo.setDataScopeVos(dataScopeVos);
        }
        UserinfoAdditionalVo<DataScopeVo> dataScopeAdditionalVo = null;
        List<UserinfoAdditionalVo<DataScopeVo>> dataScopeAdditionalVos = new ArrayList<>();
        List<DataScope> dataScopes = null;
        for (UserLoginHelperService.DataScopeFrom dataScopeFrom : dataScopesByUserId.getDataMap().keySet()) {
            dataScopes = dataScopesByUserId.getDataMap().get(dataScopeFrom);
            if (!isEmpty(dataScopes)) {
                dataScopeAdditionalVo = new UserinfoAdditionalVo();
                dataScopeAdditionalVo.setData(dataScopes.stream().map(dataScope -> dataScopeWebMapper.poToVo(dataScope)).collect(Collectors.toList()));
                dataScopeAdditionalVos.add(dataScopeAdditionalVo);
            }
        }
        currentUserinfoVo.setDataScopeAddtionalVos(dataScopeAdditionalVos);

    }
    /**
     * 修改个人信息
     * @return
     */
    @ApiOperation("修改个人信息")
    @PreAuthorize("hasAuthority('user')")
    @PutMapping("/userinfo/current")
    @ResponseStatus(HttpStatus.CREATED)
    public UserinfoVo currentUserinfoEdit(@RequestBody @Valid UserinfoUpdateForm form, LoginUser loginUser) {
        User user = userWebMapper.formToPo(form);
        user.setId(loginUser.getId());
        boolean r = iUserService.updateById(user);
        if (!r) {
            throw ExceptionTools.failRE("更新失败，请刷新数据后再试");
        }
        return currentUserinfo(loginUser);
    }
    /**
     * 修改个人头像
     * @return
     */
    @ApiOperation("修改个人头像")
    @PreAuthorize("hasAuthority('user')")
    @PutMapping("/userinfo/current/avatar")
    @ResponseStatus(HttpStatus.CREATED)
    public UserinfoVo currentUserAvatarEdit(@RequestBody @Valid UserinfoAvatarUpdateForm form, LoginUser loginUser) {
        User user = userWebMapper.formToPo(form);
        user.setId(loginUser.getId());
        boolean r = iUserService.updateById(user);
        if (!r) {
            throw ExceptionTools.failRE("更新失败，请刷新数据后再试");
        }
        return currentUserinfo(loginUser);
    }
}
